package cyx.example.ddd.domain.order.model.aggregate;

import cyx.example.ddd.domain.order.event.OrderCancelledEvent;
import cyx.example.ddd.domain.order.event.OrderCreatedEvent;
import cyx.example.ddd.domain.order.event.OrderPaidEvent;
import cyx.example.ddd.domain.order.model.entity.OrderItem;
import cyx.example.ddd.domain.order.model.valueobject.Money;
import cyx.example.ddd.domain.order.model.valueobject.OrderStatus;
import cyx.example.ddd.domain.shared.AggregateRoot;
import lombok.Getter;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Currency;
import java.util.List;

/**
 * 订单聚合根
 * 
 * 注意：这是一个示例实现，在实际企业项目中，可能需要考虑：
 * 1. 更复杂的状态机管理
 * 2. 业务规则验证
 * 3. 事件版本兼容性
 * 4. 聚合根大小控制
 */
@Getter
public class Order extends AggregateRoot<String> {
    private final String userId;
    private final List<OrderItem> orderItems;
    private final Instant createdAt;
    private Money totalAmount;
    private OrderStatus status;
    private String cancelReason;

    public Order(String userId, Currency currency) {
        this.userId = userId;
        this.orderItems = new ArrayList<>();
        this.createdAt = Instant.now();
        this.totalAmount = Money.ZERO(currency);
        this.status = OrderStatus.CREATED;

        // 发布订单创建事件
        addDomainEvent(new OrderCreatedEvent(this));
        incrementVersion();
    }

    /**
     * 添加订单项
     */
    public void addOrderItem(String productId, String productName, Money unitPrice, int quantity) {
        if (status != OrderStatus.CREATED) {
            throw new IllegalStateException("Cannot modify items for order in status: " + status);
        }

        OrderItem orderItem = new OrderItem(productId, productName, unitPrice, quantity);
        orderItems.add(orderItem);
        recalculateTotalAmount();
        incrementVersion();
    }

    /**
     * 重新计算总金额
     */
    private void recalculateTotalAmount() {
        this.totalAmount = orderItems.stream()
                .map(OrderItem::getTotalPrice)
                .reduce(Money.ZERO(getCurrency()), Money::add);
    }

    /**
     * 获取订单使用的货币
     */
    public Currency getCurrency() {
        return totalAmount.getCurrency();
    }

    /**
     * 获取订单项列表（不可修改）
     */
    public List<OrderItem> getOrderItems() {
        return Collections.unmodifiableList(orderItems);
    }

    /**
     * 支付订单
     */
    public void pay() {
        if (status != OrderStatus.CREATED) {
            throw new IllegalStateException("Cannot pay order in status: " + status);
        }
        status = OrderStatus.PAID;

        // 发布订单支付事件
        addDomainEvent(new OrderPaidEvent(this));
        incrementVersion();
    }

    /**
     * 确认订单
     */
    public void confirm() {
        if (status != OrderStatus.PAID) {
            throw new IllegalStateException("Cannot confirm order in status: " + status);
        }
        status = OrderStatus.CONFIRMED;
        incrementVersion();
    }

    /**
     * 开始配送
     */
    public void startShipping() {
        if (status != OrderStatus.CONFIRMED) {
            throw new IllegalStateException("Cannot start shipping order in status: " + status);
        }
        status = OrderStatus.SHIPPING;
        incrementVersion();
    }

    /**
     * 完成订单
     */
    public void complete() {
        if (status != OrderStatus.SHIPPING) {
            throw new IllegalStateException("Cannot complete order in status: " + status);
        }
        status = OrderStatus.COMPLETED;
        incrementVersion();
    }

    /**
     * 取消订单
     */
    public void cancel(String reason) {
        if (status == OrderStatus.SHIPPING || status == OrderStatus.COMPLETED || status == OrderStatus.CANCELLED) {
            throw new IllegalStateException("Cannot cancel order in status: " + status);
        }
        this.cancelReason = reason;
        status = OrderStatus.CANCELLED;

        // 发布订单取消事件
        addDomainEvent(new OrderCancelledEvent(this, reason));
        incrementVersion();
    }
}